package com.jesse.blurbenchmark.blur;

import java.util.concurrent.atomic.AtomicBoolean;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.os.SystemClock;
import android.support.v8.renderscript.RenderScript;
import android.view.View;

import com.jesse.util.ViewUtil;

/**
 * 动态模糊
 * 
 * 原作者：https://github.com/patrickfav/BlurTestAndroid
 * 
 * @author jesse
 *
 */
public class BlurView {

	private AtomicBoolean isWorking = new AtomicBoolean(false);
	private Bitmap dest;
	private RenderScript rs;
	
	private int blur = 15;
	private long max=0;
	private long min=9999;
	private double avgSum =0;
	private long avgCount =0;
	private long last=0;
	private Context context;
	
	public BlurView(Context context) {
		this.context = context;
	}
	
	/**
	 * 
	 * @param context
	 * @param blur		模糊值 0~25
	 */
	public BlurView(Context context, int blur) {
		this.context = context;
		this.blur = blur;
	}
	
	public RenderScript getRs() {
		if (rs == null) {
			rs = RenderScript.create(context);
		}
		return rs;
	}
	
	/**
	 * 在使用模糊类的view中，请在destory方法中调用该方法，以防止溢出
	 */
	public void releaseBlur() {
		if (rs != null) {
			rs.destroy();
			rs = null;
		}
	}
	
	/**
	 * 模糊生成器，其原理就是使用backgroundView的拷贝来生成一个模糊的view 然后在截取出需要的高宽，
	 * 再将生成好的模糊的View设置到targetBlurView的背景中
	 * 
	 * 默认的模糊算法为RS_GAUSS_FAST, 可参考其他算法{@link EBlurAlgorithm}
	 * 
	 * 生成中请注意异常提示！！
	 * 
	 * @param targetBlurView		需要被模糊的View
	 * @param backgroundView		该View的背景view
	 */
	@SuppressWarnings("deprecation")
	public void updateBlurView(View targetBlurView, View backgroundView) {
		try {
			if (targetBlurView != null ) {
				isWorking.compareAndSet(false, true);
				long start = SystemClock.elapsedRealtime();
				dest = drawViewToBitmap(dest, backgroundView, 10);
				targetBlurView.setBackgroundDrawable(new BitmapDrawable(context.getResources(), BlurUtil.blur(getRs(), context, crop(dest.copy(dest.getConfig(), true), targetBlurView, 10), blur, EBlurAlgorithm.RS_GAUSS_FAST)));
				checkAndSetPerformanceTextView(SystemClock.elapsedRealtime() - start);
				isWorking.compareAndSet(true, false);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private void checkAndSetPerformanceTextView(long currentRunMs) {
		if(max < currentRunMs) {
			max = currentRunMs;
		}
		if(min > currentRunMs) {
			min = currentRunMs;
		}
		avgCount++;
		avgSum += currentRunMs;
		last = currentRunMs;
		ViewUtil.Debug("last: "+last+"ms / avg: "+Math.round(avgSum/avgCount)+"ms / min:"+min+"ms / max:"+max+"ms");
	}
	
	private Bitmap drawViewToBitmap(Bitmap dest, View view, int downSampling) {
		float scale = 1f / downSampling;
		int viewWidth = view.getWidth();
		int viewHeight = view.getHeight();
		int bmpWidth = Math.round(viewWidth * scale);
		int bmpHeight = Math.round(viewHeight * scale);

		if (dest == null || dest.getWidth() != bmpWidth || dest.getHeight() != bmpHeight) {
			dest = Bitmap.createBitmap(bmpWidth, bmpHeight, Bitmap.Config.ARGB_8888);
		}

		Canvas c = new Canvas(dest);
		if (downSampling > 1) {
			c.scale(scale, scale);
		}

		view.draw(c);
		return dest;
	}
	
	private Bitmap crop(Bitmap srcBmp, View canvasView, int downsampling) {
		float scale = 1f / downsampling;
		return Bitmap.createBitmap(
				srcBmp,
				(int) Math.floor((canvasView.getX())*scale),
				(int) Math.floor((canvasView.getY())*scale),
				(int) Math.floor((canvasView.getWidth())*scale),
				(int) Math.floor((canvasView.getHeight())*scale)
		);
	}
}
